package org.light.utils;

import java.util.Map;
import java.util.TreeMap;

import org.light.exception.ValidateException;

public class PluralUtil {
	public static Map<String,String> dic = new TreeMap<String,String>();
	public static Map<String,String> reversedic = new TreeMap<String,String>();
	
	static {
		dic.put("roof","roofs");
		dic.put("gulf","gulfs");
		dic.put("grief","griefs");
		dic.put("cliff","cliffs");
		dic.put("beef","beefs");
		dic.put("chief","chiefs");
		dic.put("proof","proofs");
		dic.put("staff","staffs");
		dic.put("man", "men");
		dic.put("woman", "women");
		dic.put("fireman","firemen");
		dic.put("foot","feet");
		dic.put("goose","geese");
		dic.put("tooth","teeth");
		dic.put("mouse","mice");
		dic.put("louse","lice");
		dic.put("child","children");
		dic.put("ox","oxen");
		dic.put("auto","autos");
		dic.put("kangaroo","kangaroos");
		dic.put("kilo","kilos");
		dic.put("memo","memos");
		dic.put("photo","photos");
		dic.put("piano","pianos");
		dic.put("pimento","pimentos");
		dic.put("pro","pros");
		dic.put("con","cons");
		dic.put("solo","solos");
		dic.put("soprano","sopranos");
		dic.put("studio","studios");
		dic.put("tattoo","tattoos");
		dic.put("video","videos");
		dic.put("zoo","zoos");
		dic.put("bamboo","bamboos");
		dic.put("echo","echoes");
		dic.put("embargo","embargoes");
		dic.put("hero","heroes");
		dic.put("potato","potatoes");
		dic.put("tomato","tomatoes");
		dic.put("torpedo","torpedoes");
		dic.put("veto","vetoes");
		dic.put("negro","negroes");
		dic.put("buffalo","buffalos");
		dic.put("cargo","cargos");
		dic.put("halo","halos");
		dic.put("mosquito","mosquitos");
		dic.put("motto","mottos");
		dic.put("no","nos");
		dic.put("tornado","tornados");
		dic.put("volcano","volcanos");
		dic.put("zero","zeros");
		dic.put("commando","commands");
		dic.put("cod","cod");
		dic.put("deer","deer");
		dic.put("fish","fish");
		dic.put("offspring","offspring");
		dic.put("perch","perch");
		dic.put("sheep","sheep");
		dic.put("trout","trout");
		dic.put("bison","bison");
		dic.put("moose","moose");
		dic.put("aircraft","aircraft");

		dic.put("barracks","barracks");
		dic.put("crossroads","crossroads");
		dic.put("dice","dice");
		dic.put("gallows","gallows");
		dic.put("headquarters","headquarters");
		dic.put("means","means");
		dic.put("series","series");
		dic.put("species","species");

		dic.put("alga","algae");
		dic.put("amoeba","amoebas");
		dic.put("antenna","antennas");
		dic.put("formula","formulas");
		dic.put("larva","larvae");
		dic.put("nebula","nebulas");
		dic.put("vertebra","vertebras");
		dic.put("alumna","alumnae");

		dic.put("beau","beaus");
		dic.put("bureau","bureaus");
		dic.put("tableau","tableaus");
		dic.put("plateau","plateaus");

		dic.put("corpus","corpora");
		dic.put("genus","genera");
		dic.put("alumnus","alumni");
		dic.put("bacillus","bacilli");
		dic.put("cactus","cactuses");
		dic.put("focus","foci");
		dic.put("fungus","funguses");
		dic.put("nucleus","nuclei");
		dic.put("octopus","octopuses");
		dic.put("radius","radiuses");
		dic.put("stimulus","stimuli");
		dic.put("syllabus","syllabuses");
		dic.put("terminus","termini");
		dic.put("hippopotamus","hippopotami");
		dic.put("genius","geniuses");
		dic.put("abacus","abacuses");
		dic.put("addendum","addenda");
		dic.put("bacterium","bacteria");
		dic.put("curriculum","curriculums");
		dic.put("datum","data");
		dic.put("erratum","errata");
		dic.put("medium","media");
		dic.put("memorandum","memorandums");
		dic.put("ovum","ova");
		dic.put("stratum","stratums");
		dic.put("symposium","symposiums");
		dic.put("agendum","agenda");
		dic.put("vacuum","vacuums");
		dic.put("gymnasium","gymnasia");
		dic.put("stadium","stadiums");
		dic.put("forum","forums");
		dic.put("minimum","minima");
		dic.put("ultimatum","ultimatums");
		dic.put("apex","apexes");
		dic.put("appendix","appendixes");
		dic.put("cervix","cervixes");
		dic.put("index","indexes");
		dic.put("matrix","matrixes");
		dic.put("vortex","vortexes");
		dic.put("analysis","analyses");
		dic.put("axis","axes");
		dic.put("basis","bases");
		dic.put("crisis","crises");
		dic.put("diagnosis","diagnoses");
		dic.put("emphasis","emphases");
		dic.put("hypothesis","hypothesesx");
		dic.put("neurosis","neuroses");
		dic.put("oasis","oases");
		dic.put("parenthesis","parentheses");
		dic.put("synopsis","synopses");
		dic.put("thesis","theses");
		dic.put("ellipsis","ellipses");
		dic.put("synthesis","syntheses");
		dic.put("criterion","criteria");
		dic.put("phenomenon","phenomena");
		dic.put("automaton","automata");
		dic.put("libretto","libretti");
		dic.put("tempo","tempi");
		dic.put("virtuoso","virtuosos");
		dic.put("concerto","concerti");
		dic.put("cherub","cherubim");
		dic.put("seraph","seraphim");
		dic.put("schema","schemata");
		dic.put("stigma","stigmata");
		dic.put("abacus","abacuses");
		dic.put("addendum","addenda");
		dic.put("agendum","agenda");
		dic.put("aircraft","aircraft");
		dic.put("alga","algae");
		dic.put("alumna","alumnae");
		dic.put("alumnus","alumni");
		dic.put("analysis","analyses");
		dic.put("antenna","antennae");
		dic.put("apex","apexes");
		dic.put("appendix","appendixes");
		dic.put("automaton","automata");
		dic.put("axis","axes");
		dic.put("bacillus","bacilli");
		dic.put("bacterium","bacteria");
		dic.put("basis","bases");
		dic.put("beau","beaux, beaus");
		dic.put("beef","beefs");
		dic.put("bison","bison");
		dic.put("brace","brace");
		dic.put("sister-in-law","sisters-in-law");
		dic.put("buffalo","buffalo");
		dic.put("bureau","bureaux, bureaus");
		dic.put("bus","buses");
		dic.put("cactus","cacti");
		dic.put("calf","calves");
		dic.put("cargo","cargoes");
		dic.put("cervix","cervixes");
		dic.put("cherub","cherubim");
		dic.put("chief","chiefs");
		dic.put("child","children");
		dic.put("Chinese","Chinese");
		dic.put("cliff","cliffs");
		dic.put("cod","cod");
		dic.put("corps","corps");
		dic.put("corpus","corpuses");
		dic.put("crisis","crises");
		dic.put("criterion","criteria");
		dic.put("curriculum","curriculums");
		dic.put("datum","data");
		dic.put("deer","deer");
		dic.put("dice","dice");
		dic.put("dwarf","dwarves");
		dic.put("diagnosis","diagnoses");
		dic.put("echo","echoes");
		dic.put("elf","elves");
		dic.put("ellipsis","ellipses");
		dic.put("embargo","embargoes");
		dic.put("emphasis","empha ses");
		dic.put("erratum","errata");
		dic.put("fireman","firemen");
		dic.put("fish","fishes");
		dic.put("focus","focuses");
		dic.put("foot","feet");
		dic.put("formula","formulas");
		dic.put("forum","forums");
		dic.put("fungus","funguses");
		dic.put("genus","genera");
		dic.put("goose","geese");
		dic.put("gallows","gallows");
		dic.put("genius","geniuses");
		dic.put("goosefoot","goosefoots");
		dic.put("grief","griefs");
		dic.put("gulf","gulfs");
		dic.put("gymnasium","gymnasia");
		dic.put("half","halves");
		dic.put("halo","haloes");
		dic.put("headquarters","headquarters");
		dic.put("hero","heroes");
		dic.put("hippopotamus","hippopotamuses");
		dic.put("hoof","hooves");
		dic.put("hypothesis","hypotheses");
		dic.put("index","indexes");
		dic.put("knife","knives");
		dic.put("larva","larvae");
		dic.put("leaf","leaves");
		dic.put("libretto","libretti");
		dic.put("life","lives");
		dic.put("loaf","loaves");
		dic.put("louse","lice");
		dic.put("looker-on","lookers-on");
		dic.put("mandoctor","mendoctors");
		dic.put("manservant","menservants");
		dic.put("man-time","men-times");
		dic.put("man-day","man-days");
		dic.put("matrix","matrixes");
		dic.put("means","means");
		dic.put("medium","media");
		dic.put("memorandum","memorandums");
		dic.put("millennium","millenniums");
		dic.put("moose","moose");
		dic.put("mosquito","mosquitos");
		dic.put("mouse","mice");
		dic.put("nebula","nebulas");
		dic.put("neurosis","neuroses");
		dic.put("no","noes");
		dic.put("nucleus","nuclei");
		dic.put("oasis","oases");
		dic.put("octopus","octopuses");
		dic.put("offspring","offspring");
		dic.put("optimum","optima");
		dic.put("ovum","ova");
		dic.put("ox","oxen");
		dic.put("paralysis","paralyses");
		dic.put("parenthesis","parentheses");
		dic.put("penny","pence");
		dic.put("perch","perch");
		dic.put("person","people");
		dic.put("phenomenon","phenomena");
		dic.put("radius","radiuses");
		dic.put("scarf","scarves");
		dic.put("schema","schemata");
		dic.put("seed","seeds");
		dic.put("self","selves");
		dic.put("seraph","seraphim");
		dic.put("series","series");
		dic.put("sheaf","sheaves");
		dic.put("sheep","sheep");
		dic.put("shelf","shelves");
		dic.put("shrimp","shrimp");
		dic.put("scissors","scissors");
		dic.put("species","species");
		dic.put("stadium","stadiums");
		dic.put("stimulus","stimuli");
		dic.put("stratum","stratums");
		dic.put("swiss","swiss");
		dic.put("syllabus","syllabuses");
		dic.put("symposium","symposiums");
		dic.put("synthesis","syntheses");
		dic.put("synopsis","synopses");
		dic.put("ableau","tableaus");
		dic.put("tempo","tempi");
		dic.put("terminus","termini");
		dic.put("that","those");
		dic.put("thesis","theses");
		dic.put("thief","thieves");
		dic.put("this","these");
		dic.put("tooth","teeth");
		dic.put("tornado","tornadoes");
		dic.put("torpedo","torpedoes");
		dic.put("trout","trout");
		dic.put("trousers","trousers");
		dic.put("vacuum","vacuums");
		dic.put("vertebra","vertebras");
		dic.put("veto","vetoes");
		dic.put("virtuoso","virtuosos");
		dic.put("vita","vitae");
		dic.put("volcano","volcanoes");
		dic.put("postman", "postmen");
		
		dic.put("leave", "leaves");
		dic.put("course","courses");

		reversedic = reverseMap(dic);
	}
	
	public static Map<String,String> reverseMap(Map<String,String> map){
		Map<String,String> result = new TreeMap<>();
		for (String key: map.keySet()) {
			String val = map.get(key);
			result.put(val.trim().toLowerCase(), key.trim().toLowerCase());
		}
		return result;
	}

	public static String lookupDicPlural(String word) {
		return dic.get(word);		
	}
	
	public static String lookupReverseDicSingle(String plural) {
		return reversedic.get(plural.toLowerCase());		
	}
	
	public static String lookupPlural(String word) throws ValidateException{
		String lastWord = findLastWord(word);
		String wordPrefix = findWordPrefix(word);
		String lookupPlural = lookupDicPlural(StringUtil.lowerFirst(lastWord));	
		if (StringUtil.isBlank(lookupPlural)) {
			String sName = StringUtil.lowerFirst(lastWord);
			String lastPlural = "";
			if (sName.endsWith("ay")||sName.endsWith("ey")||sName.endsWith("iy")||sName.endsWith("oy")||sName.endsWith("uy")) {
				lastPlural = StringUtil.capFirst(sName) + "s";
			}else if (sName.endsWith("y")) {
				lastPlural = StringUtil.capFirst(sName.substring(0,sName.length()-1))+"ies";
			}else if (sName.endsWith("o")&&(sName.endsWith("a")||sName.endsWith("e")||sName.endsWith("i")||sName.endsWith("o")||sName.endsWith("u"))) {
				lastPlural = StringUtil.capFirst(sName) + "s";
			}else if (sName.endsWith("o")&&!(sName.endsWith("a")||sName.endsWith("e")||sName.endsWith("i")||sName.endsWith("o")||sName.endsWith("u"))) {
				lastPlural = StringUtil.capFirst(sName) + "es";
			}else if (sName.endsWith("s")||sName.endsWith("x")||sName.endsWith("ch") || sName.endsWith("sh")) {
				lastPlural = StringUtil.capFirst(sName) + "es";
			} else if (sName.endsWith("f")) {
				lastPlural = StringUtil.capFirst(sName.substring(0,sName.length()-1)) + "ves";
			} else if (sName.endsWith("fe")) {
				lastPlural = StringUtil.capFirst(sName.substring(0,sName.length()-2)) + "ves";
			} else if (StringUtil.isBlank(sName)) {
				lastPlural = "s";
			}else {
				lastPlural = StringUtil.capFirst(sName) + "s";
			}
			return wordPrefix+lastPlural;
		}else {
			if (lookupPlural.equals(lastWord)) lookupPlural += "s";
			return StringUtil.capFirst(wordPrefix) + StringUtil.capFirst(lookupPlural); 
		}			
	}
	
	public static String lookupSingle(String plural) throws ValidateException{
		if (StringUtil.isBlank(plural)) return "";
		String lastWord = findLastWord(plural);
		String wordPrefix = findWordPrefix(plural);
		String lookupSingle = lookupReverseDicSingle(StringUtil.lowerFirst(lastWord));	
		if (StringUtil.isBlank(lookupSingle)) {
			String sName = StringUtil.lowerFirst(lastWord);
			String single = "";
			if (sName.endsWith("ays")||sName.endsWith("eys")||sName.endsWith("iys")||sName.endsWith("oys")||sName.endsWith("uys")) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-1));
			}else if (sName.endsWith("ies")) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-3))+"y";
			}else if (sName.endsWith("os")&&(sName.endsWith("as")||sName.endsWith("es")||sName.endsWith("is")||sName.endsWith("os")||sName.endsWith("us"))) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-1));
			}else if (sName.endsWith("oes")&&!(sName.endsWith("aes")||sName.endsWith("ees")||sName.endsWith("ies")||sName.endsWith("oes")||sName.endsWith("ues"))) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-2));
			}else if (sName.endsWith("ses")||sName.endsWith("xes")||sName.endsWith("ches") || sName.endsWith("shes")) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-2));
			} else if (sName.endsWith("ves")) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-3)) + "f";
			} else if (sName.endsWith("s")) {
				single = StringUtil.capFirst(sName.substring(0,sName.length()-1));
			} else {
				single =  StringUtil.capFirst(sName.substring(0,sName.length()));
			}
			return wordPrefix+single;
		}else {			
			return StringUtil.capFirst(wordPrefix) + StringUtil.capFirst(lookupSingle); 
		}			
	}
	
	public static Map<String,String> lookupSingleAndPlural(String plural) throws ValidateException{
		plural = StringUtil.capFirst(plural);
		Map<String,String> result = new TreeMap<>();
		String single = lookupSingle(plural);
		if (single.equals(plural)) {
			String lookupPlural = lookupPlural(single);
			if (lookupPlural.equals(single)) lookupPlural = single+"s";
			result.put("single", single);
			result.put("plural", lookupPlural);
		} else {
			result.put("single", single);
			result.put("plural", plural);
		}
		return result;
	}
	
	public static String findLastWord(String fullWord) {
		String snakeWord = StringUtil.changeDomainFieldtoTableColum(fullWord);
		if (!snakeWord.contains("_")) return fullWord;
		String snakeLastWord = snakeWord.substring(snakeWord.lastIndexOf("_")+1,snakeWord.length());
		return StringUtil.capFirst(snakeLastWord);
	}
	
	public static String findWordPrefix(String fullWord) throws ValidateException {
		String snakeWord = StringUtil.changeDomainFieldtoTableColum(fullWord);
		if (!snakeWord.contains("_")) return "";
		String snakePrefix = snakeWord.substring(0,snakeWord.lastIndexOf("_"));
		return StringUtil.capFirst(StringUtil.changeTableColumtoDomainField(snakePrefix));
	}
	
	public static void main(String[] args) throws ValidateException{
		/*System.out.println("goose:"+lookupPlural("goose"));
		System.out.println("person:"+lookupPlural("person"));
		System.out.println("category:"+lookupPlural("category"));
		System.out.println("tooth:"+lookupPlural("tooth"));
		System.out.println("man:"+lookupPlural("man"));
		System.out.println("woman:"+lookupPlural("woman"));
		System.out.println("frog:"+lookupPlural("frog"));*/
		System.out.println("teeth:"+lookupReverseDicSingle("teeth"));
		System.out.println("MyTeeth:"+lookupSingle("MyTeeth"));
		System.out.println("SysUsers:"+lookupSingle("SysUsers"));
		System.out.println("courses:"+lookupSingle("courses"));
	}
}
